/**
 * 
 */
package coop.tecso.core.test.handlers;

import java.util.Random;

import org.org.usurper.handlers.IHandler;
import org.org.usurper.handlers.basic.AbstractSpecificPropertyHandler;
import org.org.usurper.model.HandledBeanProperty;
import org.org.usurper.model.HandledConstructorArg;
import org.org.usurper.model.SpecificPropertyDefinition;

/**
 * @author daniel
 *
 */
public class UsurperHandlers {

	public static class NumericStringHandler extends AbstractSpecificPropertyHandler {

		private int length;

		/**
		 * @param specificPropertyDefinition
		 */
		public NumericStringHandler(SpecificPropertyDefinition specificPropertyDefinition, int length) {
			super(specificPropertyDefinition);
			this.length = length;
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledBeanProperty)
		 */
		@Override
		public Object handle(HandledBeanProperty handledBeanProperty) {
			return doHandle();
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledConstructorArg)
		 */
		@Override
		public Object handle(HandledConstructorArg handledConstructorArg) {
			return doHandle();
		}

		private String doHandle() {
			return getRandomNumericString(length);
		}

		private String getRandomNumericString(int length) {
			Random random = new Random();
			Integer[] randoms = new Integer[length];
			for (int i = 0; i < randoms.length; i++) {
				randoms[i] = random.nextInt(10);
			}
			return org.apache.commons.lang.StringUtils.join(randoms);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Object#hashCode()
		 */
		 @Override
		 public int hashCode() {
			 final int prime = 31;
			 int result = 1;
			 result = prime * result + length;
			 return result;
		 }

		 /*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		 @Override
		 public boolean equals(Object obj) {
			 if (this == obj) {
				 return true;
			 }
			 if (obj == null) {
				 return false;
			 }
			 if (getClass() != obj.getClass()) {
				 return false;
			 }
			 NumericStringHandler other = (NumericStringHandler) obj;
			 if (length != other.length) {
				 return false;
			 }
			 return true;
		 }

	}

	public static class DomainHandler extends AbstractSpecificPropertyHandler {

		/**
		 * @param specificPropertyDefinition
		 */
		public DomainHandler(SpecificPropertyDefinition specificPropertyDefinition) {
			super(specificPropertyDefinition);
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledBeanProperty)
		 */
		@Override
		public Object handle(HandledBeanProperty handledBeanProperty) {
			return generateValidDomainName();
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledConstructorArg)
		 */
		@Override
		public Object handle(HandledConstructorArg handledConstructorArg) {
			return generateValidDomainName();
		}

		private String generateValidDomainName() {
			return "name@domain.com";
		}
	}

	public static class SequentialHandler extends AbstractSpecificPropertyHandler {

		private IHandler delegateHandler;
		private int lastInSequence = 0;

		/**
		 * @param specificPropertyDefinition
		 */
		public SequentialHandler(SpecificPropertyDefinition specificPropertyDefinition) {
			super(specificPropertyDefinition);
		}

		/**
		 * @param specificPropertyDefinition
		 * @param handler
		 */
		public SequentialHandler(SpecificPropertyDefinition specificPropertyDefinition, IHandler handler) {
			super(specificPropertyDefinition);
			delegateHandler = handler;
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledBeanProperty)
		 */
		@Override
		public Object handle(HandledBeanProperty handledBeanProperty) {
			lastInSequence++;
			if (delegateHandler == null) {
				return lastInSequence;
			}
			return delegateHandler.handle(handledBeanProperty);
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledConstructorArg)
		 */
		@Override
		public Object handle(HandledConstructorArg handledConstructorArg) {
			lastInSequence++;
			if (delegateHandler == null) {
				return lastInSequence;
			}
			return delegateHandler.handle(handledConstructorArg);
		}

	}

	public static class AutocalculatedVerificationCodeHandler extends AbstractSpecificPropertyHandler {

		/**
		 * @param specificPropertyDefinition
		 */
		public AutocalculatedVerificationCodeHandler(SpecificPropertyDefinition specificPropertyDefinition) {
			super(specificPropertyDefinition);
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledBeanProperty)
		 */
		@Override
		public Object handle(HandledBeanProperty handledBeanProperty) {
			return doHandle();
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledConstructorArg)
		 */
		@Override
		public Object handle(HandledConstructorArg handledConstructorArg) {
			return doHandle();
		}

		private String doHandle() {
			return getRandomNumericString(9);
		}

		private String getRandomNumericString(int length) {
			Random random = new Random();
			Integer[] randoms = new Integer[length];
			for (int i = 0; i < randoms.length; i++) {
				randoms[i] = random.nextInt(10);
			}
			return org.apache.commons.lang.StringUtils.join(randoms);
		}
	}

	public static class RandomMultipleHandler extends AbstractSpecificPropertyHandler {

		private int multipleOf;
		private int minimum;
		private Random random;

		/**
		 * @param specificPropertyDefinition
		 */
		public RandomMultipleHandler(SpecificPropertyDefinition specificPropertyDefinition, int multipleOf, int minimun) {
			super(specificPropertyDefinition);
			this.multipleOf = multipleOf;
			minimum = minimun;
			random = new Random();
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledBeanProperty)
		 */
		@Override
		public Object handle(HandledBeanProperty handledBeanProperty) {
			return doHandle();
		}

		/*
		 * (non-Javadoc)
		 * @see org.org.usurper.handlers.IHandler#handle(org.org.usurper.model.HandledConstructorArg)
		 */
		@Override
		public Object handle(HandledConstructorArg handledConstructorArg) {
			return doHandle();
		}

		private Integer doHandle() {
			return random.nextInt(5) * multipleOf + minimum;
		}
	}


}
